/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package com.dao.daobase;

import java.lang.reflect.ParameterizedType;
import java.util.List;
import javax.annotation.Resource;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.transaction.annotation.Propagation;
//import org.springframework.transaction.annotation.Propagation;
//import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.annotation.Transactional;

import com.yyl.common.collection.ListData;

/**
 *
 * @author admin
 */
@Transactional(propagation = Propagation.REQUIRED)
public abstract class DaoBase<Tp> implements CommonDao<Tp>{
    
    @Resource
    private SessionFactory sessionFactory;
    
    protected final Class<Tp> entityClass;
    
    protected final String entityName;
   
    
    
    public DaoBase(){
        entityClass = (Class<Tp>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        entityName = entityClass.getName().replace(entityClass.getPackage().getName(), "").substring(1);  
    }
    /**
	 * 获取当前可用的session
	 * 设置为protected，是方便子类直接调用该方法，省去再声明sessionfactory
	 * @return
	 */
    protected Session getSession(){
            return sessionFactory.getCurrentSession();
    }

    @Override
    public Tp findObject(long id) {
        return (Tp)getSession().get(entityClass, id);
    }

    @Override
    public List<Tp> findAll() {
        return (List<Tp>)getSession().createQuery("select a from "+entityName+" a").list();
    }

    @Override
    public List<Tp> findAll(String condition) {
        return (List<Tp>)getSession().createQuery("select a from "+entityName+" a where "+condition).list();
    }

    @Override
    public List<Tp> findAll(int start, int offset) {
       return (List<Tp>)getSession().createQuery("select a from "+entityName+" a").setFirstResult(start).setMaxResults(offset).list();
    }

    @Override
    public List<Tp> findAll(int start, int offset, String condition) {
        return (List<Tp>)getSession().createQuery("select a from "+entityName+" a where "+condition).setFirstResult(start).setMaxResults(offset).list();
    }

    @Override
    public List<Tp> findAll(String condition, Object... argv) {
       Query query = getSession().createQuery("select a from "+entityName+" a where "+condition);
       for(int i=0; i<argv.length; i++) {
           query.setParameter(i+1, argv[i]);
       }
       return (List<Tp>)query.list();
    }

    @Override
    public List<Tp> findAll(int start, int offset, String condition, Object... argv) {
       Query query = getSession().createQuery("select a from "+entityName+" a where "+condition);
       for(int i=0; i<argv.length; i++) {
           query.setParameter(i+1, argv[i]);
       }
       return (List<Tp>)query.setFirstResult(start).setMaxResults(offset).list();
    }

    @Override
    public ListData<Tp> list(int start, int offset) {
        ListData<Tp> ld = new ListData<>();
        ld.setList(this.findAll(start, offset));
        ld.setTotal(this.count());
        if(offset != 0) {
            ld.setTotalPage((ld.getTotal()-1)/offset);
            ld.setPage(start / offset);
        }
        return ld;
    }

    @Override
    public ListData<Tp> list(int start, int offset, String condition, Object... argv) {
        ListData<Tp> ld = new ListData<>();
        ld.setList(this.findAll(start, offset, condition, argv));
        ld.setTotal(this.count());
        if(offset != 0) {
            ld.setTotalPage((ld.getTotal()-1)/offset);
            ld.setPage(start / offset);
        }
        return ld;
    }

    @Override
    public int removeAll() {
        int reduceNumber = getSession().createQuery("delete "+entityName).executeUpdate();
        return reduceNumber;
    }

    @Override
    public int removeAll(String condition, Object... argv) {
        Query query = getSession().createQuery("delete "+entityName+" where "+condition);
        for(int i=0; i<argv.length; i++) {
            query.setParameter(i+1, argv[i]);
        }
        int reduceNumber = query.executeUpdate();
        return reduceNumber;
    }

    @Override
    public int removeObject(List<Tp> target) {
        for(Tp tp : target) {
            this.removeObject(tp);
        }
        return target.size();
    }

    @Override
    public void removeObject(Tp object) {
        getSession().delete(object);
    }

    @Override
    public List<Tp> addObject(List<Tp> list) {
        for(Tp tp : list) {
            this.addObject(tp);
        }
        return list;
    }

    @Override
    public Tp saveOrUpdateObject(Tp object) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public Tp addObject(Tp object) {
        getSession().persist(object);
        return object;
    }

    @Override
    public Tp forceAddObject(Object obj) {
        if(obj.getClass().equals(entityClass)) {
            this.addObject((Tp)obj);
        }
        return (Tp)obj;
    }

    @Override
    public Tp mergeObject(Tp object) {
        return (Tp)getSession().merge(object);
    }

    @Override
    public Tp forceMergeObject(Object obj) {
        if(obj.getClass().equals(entityClass)) {
            this.mergeObject((Tp)obj);
        }
        return (Tp)obj;
    }

    @Override
    public int count() {
        return ((Integer)getSession().createQuery("select count(a) from "+entityName+" a").uniqueResult());
    }

    @Override
    public int count(String condition) {
        return ((Integer)getSession().createQuery("select count(a) from "+entityName+" a where "+condition).uniqueResult());
    }

    @Override
    public int count(String condition, Object... argv) {
        Query query = getSession().createQuery("select count(a) from "+entityName+" a where "+condition);
        for(int i=0; i<argv.length; i++) {
            query.setParameter(i+1, argv[i]);
        }
        return (Integer)query.uniqueResult();
    }

    @Override
    public Tp getReference(long id) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public void refreshObject(Tp object) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public void flushContext() {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public List<Tp> findLast(int n) {
        return null;
    }

    @Override
    public List<Tp> findLast(String condition, int n) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public List<Tp> findLast(String condition, int n, Object... argv) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public Tp findOne() {
        Query query = getSession().createQuery("select a from "+entityName+" a");
        query.setFirstResult(0).setMaxResults(1);
        List<Tp> resultList = query.list();
        if(resultList.isEmpty()) {
            return null;
        } else {
            return resultList.get(0);
        }
    }

    @Override
    public Tp findOne(String condition) {
        Query query = getSession().createQuery("select a from "+entityName+" a where "+condition);
        query.setFirstResult(0).setMaxResults(1);
        List<Tp> resultList = query.list();
        if(resultList.isEmpty()) {
            return null;
        } else {
            return resultList.get(0);
        }
    }

    @Override
    public Tp findOne(String condition, Object... argv) {
        Query query = getSession().createQuery("select a from "+entityName+" a where "+condition);
        for(int i=0; i<argv.length; i++) {
            query.setParameter(i+1, argv[i]);
        }
        query.setFirstResult(0).setMaxResults(1);
        List<Tp> resultList = query.list();
        if(resultList.isEmpty()) {
            return null;
        } else {
            return resultList.get(0);
        }
    }

    @Override
    public Query query(String query) {
        return getSession().createQuery(query);
    }

    @Override
    public Query query(String query, Object... argv) {
        Query qu = getSession().createQuery(query);
        for(int i=0;i<argv.length;i++) {
            qu.setParameter(i+1, argv[i]);
        }
        return qu;
    }

    @Override
    public Query nativeQuery(String query, Object... argv) {
        return null;
    }

    @Override
    public Class<? extends Tp> getEntityClass() {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public String getEntityName() {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public void beginTransaction() {
        getSession().getTransaction().begin();
    }

    @Override
    public void commitTransaction() {
        getSession().getTransaction().commit();
    }

    @Override
    public void rollbackTransaction() {
        getSession().getTransaction().rollback();
    }
    
    
    
}
